<?php

namespace app\common\service;

use app\common\model\File as FileMdl;

//use think\File;
use think\facade\Db;
use think\Exception;

class Uploader
{
    /**
     * 文件上传
     */
    public static function upload($request)
    {
        $param = $request->param();
        if (!empty($param['total_count']) && !empty($param['total_count'])) {
            if (!empty($param['multi']) && $param['multi'] == 'true') {
                if ($param['total_count'] - $param['count'] <= 0) {
                    return json(['code' => 0, 'msg' => '最多上传' . $param['total_count'] . '张']);
                }
            }
        }

        $folder = $param['folder'] ?? 'default';
        $field = $param['field'] ?? 'file';

        $config = Config::getUploadSetting();
        $storage = $config['storage'] ?? 'local';
        if (isset($param['place'])) {
            $storage = $param['place'] ?? 'local';
        }

        try {
            $file = request()->file($field);
            if (!$file) {
                return json(['code' => 0, 'msg' => '请选择文件']);
            }
            $mimetypes = $config['mimetype'] ?? [];
            //$max_filesizes = $config['max_filesizes'] ?? [];
            //$fileexts = $config['fileexts'] ?? [];
            //$file_ext  = $file->extension();
            $file_ori_name = $file->getOriginalName();
            $file_ori_extension = $file->getOriginalExtension();
            $file_ext = strtolower($file_ori_extension);
            if (empty($file_ext)) {
                return json(['code' => 0, 'msg' => '上传的文件格式不允许']);
            }
            $file_type = FileService::typeJudge($file_ext);
            if (!in_array($file_type, ['image', 'video', 'audio'])) {
                $file_type = 'file';
            }
            $file_size = $file->getSize(); // 单位：字节
            // 验证
            if ($mimetypes && isset($mimetypes[$file_type])) {
                $max_filesize = $mimetypes[$file_type]['max_filesize'];
                $fileexts = $mimetypes[$file_type]['extensions'];
                $fileexts_arr = explode(',', $fileexts);
                if (!in_array($file_ext, $fileexts_arr)) {
                    return json(['code' => 0, 'msg' => '上传的文件格式不允许，允许格式：' . $fileexts]);
                }
                $max_filesize_byte = $max_filesize * 1024; // 转为字节
                if ($file_size > $max_filesize_byte) {
                    return json(['code' => 0, 'msg' => '上传的文件大小不允许，允许大小：' . $max_filesize . ' KB']);
                }
            }

            if ($storage == 'local') {
                // 上传到本地
                $disk = $param['disk'] ?? '';
                if ($disk && $disk == 'public') {
                    $disk = 'public';
                } else {
                    $disk = 'uploads';
                }
                // 移动到框架应用根目录/public/uploads/ 目录下
                //$image_rule = ['image' => 'fileSize:512000|fileExt:jpg,jpeg,png,gif'];
                //validate($validate_rule)->check(['image' => $file]);
                //$file_rule = ['file' => ['fileSize' => 1024, 'fileExt' => 'jpg,jpeg,png,gif']];
                //validate($file_rule)->check(['file' => $file]);
                $folderName = $folder . '/' . date('Y-m') . '/' . date('d');
                $rename = $param['rename'] ?? '';
                if ($rename == 'false') {
                    $saveName = date('His') . '_' . $file_ori_name;
                } else {
                    $saveName = uniqid() . '.' . $file_ori_extension;
                }
                $result = $file->move($disk . '/' . $folderName, $saveName);
                if ($result) {
                    //$file_ext  = $file->extension();
                    $filePath = $folderName . '/' . $saveName;
                    $fullFilePath = asset(config('path.upload_path') . $filePath);
                } else {
                    // 上传失败获取错误信息
                    return json(['code' => 0, 'msg' => 'error']);
                }
            } elseif ($storage == 'qiniu') {
                // 上传到七牛
                $qiniu = new Qiniu();
                $result = $qiniu->uploadFile($_FILES[$field]);
                if ($result['code'] == 1) {
                    $filePath = $qiniu->url . $result['key'];
                    $fullFilePath = $filePath;
                } else {
                    return json(['code' => 0, 'msg' => $result['msg']]);
                }
            } elseif ($storage == 'tencentyun') {
                // 上传到腾讯云
                $qcloud = new Qcloud();
                $result = $qcloud->uploadFile($_FILES[$field]);
                if ($result['code'] == 1) {
                    $filePath = $qcloud->url . $result['key'];
                    $fullFilePath = $filePath;
                } else {
                    return json(['code' => 0, 'msg' => '', 'result' => $result]);
                }
            }

            // 插入uploads表记录
            $fileData = [
                //'id' => get_UUID(),
                'created_at' => time(),
                'file_name' => $file_ori_name,
                'file_url' => $filePath,
                'file_type' => $file_type,
                'file_size' => $file_size,
                'file_ext' => $file_ext,
                'folder' => $folder,
                'storage' => $storage,
                'status' => 0
            ];
            FileMdl::insert($fileData);
            return json([
                'code' => 1,
                'msg' => '上传成功',
                'filename' => $file_ori_name,
                'filesize' => $file_size,
                'filepath' => $filePath,
                'full_filepath' => $fullFilePath,
                'result' => $result
            ]);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => $e->getMessage()]);
        }
    }

    /**
     * 分片上传
     */
    public static function sliceUpload($request)
    {
        $param = $request->param();
        $folder = $param['folder'] ?? 'slice';
        $field = $param['field'] ?? 'file';

        $storage = $param['place'] ?? 'local';
        if ($storage == 'local') {
            $file = request()->file($field);
            $page = $param['page'];
            $totalPage = $param['total_page'];
            $originalName = $param['file_name'];

            if ($file) {
                $ext = pathinfo($originalName, PATHINFO_EXTENSION); // 扩展名
                //$realPath = $file->getRealPath(); // 临时文件的绝对路径

                $disk = $param['disk'] ?? '';
                if ($disk && $disk == 'public') {
                    $disk = 'public';
                } else {
                    $disk = 'uploads';
                }
                $folderName = $folder . '/' . date('Y-m') . '/' . date('d');
                $filename = $folderName . '/' . $originalName;
                $saveFilename = $folderName . '/' . uniqid() . '.' . $ext;

                /*$saveName = \think\facade\Filesystem::disk('uploads')->putFileAs($folderName, $file, $originalName. '_' . $page);
                // 判断是否是最后一块，如果是则进行文件合成并且删除文件块
                if ($page == $totalPage) {
                    for ($i = 1; $i <= $totalPage; $i++) {
                        $blob_path = \think\facade\Filesystem::disk('uploads')->path($filename . '_' . $i);
                        $blob = file_get_contents('compress.zlib://'. $blob_path); // 没有这一步文件就打不开
                        file_put_contents(public_path('uploads') . $saveFilename, $blob, FILE_APPEND);
                    }
                    // 合并完删除文件块
                    for ($i = 1; $i <= $totalPage; $i++) {
                        \think\facade\Filesystem::disk('uploads')->delete($filename . '_' . $i);
                    }
                }*/
                $result = $file->move($disk . '/' . $folderName, $originalName. '_' . $page);
                // 判断是否是最后一块，如果是则进行文件合成并且删除文件块
                if ($page == $totalPage) {
                    for ($i = 1; $i <= $totalPage; $i++) {
                        $blob_path = public_path('uploads') . $filename . '_' . $i;
                        $blob = file_get_contents('compress.zlib://'. $blob_path); // 没有这一步文件就打不开
                        file_put_contents(public_path('uploads') . $saveFilename, $blob, FILE_APPEND);
                    }
                    // 合并完删除文件块
                    for ($i = 1; $i <= $totalPage; $i++) {
                        unlink(public_path('uploads') . $filename . '_' . $i);
                    }
                }

                if ($result) {
                    $code = 2;
                    $msg = '分片上传中';
                    if ($page == $totalPage) {
                        $code = 1;
                        $msg = '上传成功';
                    }
                    return json([
                        'code' => $code,
                        'msg' => $msg,
                        'filepath' => $saveFilename,
                        'full_filepath' => asset(config('path.upload_path') . $saveFilename),
                    ]);
                } else {
                    return json([
                        'code' => 0,
                        'msg' => '上传失败'
                    ]);
                }
            }
        }
    }

    /**
     * 初始化菜单
     */
    public function initMenu(Request $request)
    {
        $menus = $this->menuCache();
        if (!$menus ) {
            return '';
        }
        $subMenu = function ($menus, $level = 0) use (&$subMenu) {
            $output = '';
            foreach ($menus as $menu) {
                // route access check
                if ($this->admin->type != 1 && !in_array($menu['id'], $this->access) && !in_array(strtolower($menu['route']), ['admin/dashboard'])) {
                    continue;
                }

                if ($level == 0) {
                    $icon = $menu['icon'];

                    $active = '';
                    if ($menu['route'] == 'dashboard') {
                        $active = 'layui-this';
                    }
                    if (empty($menu['items'])) {
                        $url = '';
                        $menu['route'] && $url = url($menu['app'] . '/' . $menu['route']);
                        $output .= '<li class="layui-nav-item ' . $active . '" data-name="' . $menu['name'] . '">';
                        $output .= '<a lay-href="' . $url . '" lay-tips="' . $menu['name'] . '" target="' . $menu['target'] . '">';
                        $output .= '<i class="layui-icon ' . $icon . '"></i>';
                        $output .= '<cite>' . $menu['name'] . '</cite>';
                        $output .= '</a>';
                        $output .= '</li>';
                    } else {
                        $output .= '<li class="layui-nav-item" data-name="' . $menu['name'] . '">';
                        $output .= '<a href="javascript:;" lay-tips="' . $menu['name'] . '">';
                        $output .= '<i class="layui-icon ' . $icon . '"></i>';
                        $output .= '<cite>' . $menu['name'] . '</cite>';
                        $output .= '</a>';
                        $output .= '<dl class="layui-nav-child">';
                        $output .= $subMenu($menu['items'], $level + 1);
                        $output .= '</dl>';
                        $output .= '</li>';
                    }
                } else {
                    if (empty($menu['items'])) {
                        $url = '';
                        $menu['route'] && $url = url($menu['app'] . '/' . $menu['route']);
                        $output .= '<dd class="">';
                        $output .= '<a lay-href="' . $url . '" target="' . $menu['target'] . '">';
                        $output .= $menu['name'];
                        $output .= '</a>';
                        $output .= '</dd>';
                    } else {
                        $output .= '<dd class=" " data-name="' . $menu['name'] . '">';
                        $output .= '<a href="javascript:;" lay-tips="' . $menu['name'] . '">';
                        $output .= $menu['name'];
                        $output .= '</a>';
                        $output .= '<dl class="layui-nav-child">';
                        $output .= $subMenu($menu['items'], $level + 1);
                        $output .= '</dl>';
                        $output .= '</dd>';
                    }
                }
            }
            return $output;
        };
        $output = $subMenu($menus);

        return $output;
    }
}
